package com.mark.mall.admin.platform.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.mark.mall.admin.platform.dto.PageParamDTO;
import com.mark.mall.admin.platform.dto.ProductDTO;
import com.mark.mall.admin.platform.dto.ProductStockDTO;
import com.mark.mall.admin.platform.dto.param.ProductAddParam;
import com.mark.mall.admin.platform.dto.param.ProductUpdateParam;
import com.mark.mall.admin.platform.entity.Product;
import com.mark.mall.admin.platform.mapper.ProductMapper;
import com.mark.mall.admin.platform.service.ProductService;
import com.mark.mall.common.constans.PlatformConstant;
import com.mark.mall.common.myException.MyException;
import com.mark.mall.common.resultBean.R;
import com.mark.mall.common.utils.GetBase64Utils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.math.BigDecimal;

/**
 * <p>
 * 物料表 服务实现类
 * </p>
 *
 * @author admin
 * @since 2021-02-28
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements ProductService {
    private final RestHighLevelClient restHighLevelClient;

    @Override
    public PageInfo<ProductDTO> getProductPage(int curPage, int pageSize, String code) {
        return PageMethod.startPage(curPage, pageSize).doSelectPageInfo(
                () -> list(Wrappers.lambdaQuery(BeanUtil.copyProperties(code, Product.class))));
    }

    @Override
    public R<Boolean> addProduct(ProductAddParam productAddParam) throws Exception {
        if (productAddParam.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw new MyException("物料价格不能小于0");
        }
        if (productAddParam.getStock() < 0) {
            throw new MyException("物料库存不能小于0");
        }
        // 将前端传入参数进行实体类复制
        Product p = BeanUtil.copyProperties(productAddParam, Product.class);
        // 赋值搜索字段
        p.setSearchkeywords(productAddParam.getCode() + productAddParam.getName());
        // 上架数量默认为0
        p.setShelfnum(0);
        p.setShelfstate(PlatformConstant.STATE_YES);
        // 同步ES引擎
        BulkRequest request = new BulkRequest();
        request.add(
                new IndexRequest(
                        PlatformConstant.INDEX_NAME).source(JSON.toJSONString(p), XContentType.JSON));
        restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
        return baseMapper.insert(p) > 0 ? new R<>(true, "新增成功！") : new R<>(false, "新增失败！");
    }

    @Override
    public R<Boolean> delProduct(String ids) throws Exception {
        if (StringUtils.isEmpty(ids)) {
            throw new MyException("参数缺失,请核实!");
        }
        if (ids.contains(",")) {
            String[] idS = ids.split(",");
            if (idS.length > 0) {
                for (String id : idS) {
                    return delProductCommon(id) > 0
                            ? new R<>(true, "删除成功！")
                            : new R<>(false, "删除失败！");
                }
            }
        } else {
            return delProductCommon(ids) > 0
                    ? new R<>(true, "删除成功！")
                    : new R<>(false, "删除失败！");
        }
        return new R<>(false, "操作失败！");
    }

    @Override
    public R<Boolean> shelfProduct(String ids, String shelfState) throws Exception {
        if (StringUtils.isEmpty(ids) || StringUtils.isEmpty(shelfState)) {
            throw new MyException("参数缺失,请核实!");
        }
        if (ids.contains(",")) {
            String[] idS = ids.split(",");
            if (idS.length > 0) {
                for (String id : idS) {
                    return shelfStateCommon(id, shelfState)
                            ? new R<>(true, "修改成功！")
                            : new R<>(true, "修改失败！");
                }
            }
        } else {
            return shelfStateCommon(ids, shelfState)
                    ? new R<>(true, "修改成功！")
                    : new R<>(true, "修改失败！");
        }
        return new R<>(false, "操作失败！");
    }

    @Override
    public R<Boolean> updateProduct(ProductUpdateParam param) throws Exception {
        if (param.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
            throw new MyException("物料价格不能小于0");
        }
        Product product = baseMapper.selectById(param.getId());
        if (product == null) {
            throw new MyException("id为{" + param.getId() + "}的物料不存在");
        }
        BeanUtil.copyProperties(param, product);
        // 给搜索字段赋值，为前台搜索做准备
        product.setSearchkeywords(param.getCode() + param.getName());
        doEsSomeThing(product, PlatformConstant.INDEX_NAME, param.getId());
        return baseMapper.update(product, new QueryWrapper<Product>().lambda().eq(Product::getId, param.getId())) > 0
                ? new R<>(true, "修改成功")
                : new R<>(false, "修改失败");
    }

    @Override
    public Product getProductById(String id) {
        if (StringUtils.isEmpty(id)) {
            throw new MyException("参数缺失,请核实!");
        }
        return baseMapper.selectById(id);
    }

    @Override
    public R<PageInfo<ProductStockDTO>> productStockPageInfo(PageParamDTO pageParamDTO, String code) {
        PageInfo<ProductStockDTO> pageInfo = PageMethod.startPage(pageParamDTO.getPageNo(), pageParamDTO.getPageSize())
                .doSelectPageInfo(
                        () -> list(Wrappers.lambdaQuery(BeanUtil.copyProperties(code, Product.class)))
                );
        return new R<>(pageInfo);
    }

    @Override
    public R<Boolean> openStock(String id, int openNum) throws Exception {
        if (StringUtils.isEmpty(id) || openNum <= 0) {
            throw new MyException("参数缺失或不准确，请核实！");
        }
        Product product = baseMapper.selectById(id);
        if (product == null) {
            throw new MyException("id为{" + id + "}的物料不存在");
        }
        if (product.getStock() < openNum) {
            throw new MyException("出库数量超出库中数量，请核实或者添加库存！");
        }
        product.setStock(product.getStock() - openNum);
        product.setShelfnum(openNum + product.getShelfnum());
        doEsSomeThing(product, PlatformConstant.INDEX_NAME, id);
        int num = baseMapper.update(product, new QueryWrapper<Product>().lambda().eq(Product::getId, id));
        return num > 0
                ? new R<>(true, "出库成功！")
                : new R<>(false, "出库失败！");
    }

    @Override
    public R<Boolean> inStock(String id, int inNum) throws Exception {
        if (StringUtils.isEmpty(id) || inNum <= 0) {
            throw new MyException("参数缺失或不准确，请核实！");
        }
        Product product = baseMapper.selectById(id);
        if (product == null) {
            throw new MyException("id为{" + id + "}的物料不存在");
        }
        product.setStock(product.getStock() + inNum);
        doEsSomeThing(product, PlatformConstant.INDEX_NAME, id);
        int num = baseMapper.update(product, new QueryWrapper<Product>().lambda().eq(Product::getId, id));
        return num > 0
                ? new R<>(true, "入库成功！")
                : new R<>(false, "入库失败！");
    }

    @Override
    public R<Boolean> productMailImg(MultipartFile file, String id) throws Exception {
        if (file == null) {
            throw new MyException("上传文件缺失，请核实！");
        }
        if (StringUtils.isEmpty(id)) {
            throw new MyException("参数缺失，请核实！");
        }
        // 根据物料id获取对应的物料
        Product product = baseMapper.selectById(id);
        if (product == null) {
            throw new MyException("id为{" + id + "}的物料不存在");
        }
        // 将文件转化为流，将流转化为base64字节存入数据库中
        String base64 = GetBase64Utils.getBase64FromInputStream(file.getInputStream());
        //if (!StringUtils.isEmpty(base64)) {
        // 拼接为完整的base64
        //product.setMainurl("data:img/jpg;base64," + base64);
        update(Wrappers.<Product>lambdaUpdate().set(!StringUtils.isEmpty(base64), Product::getMainurl, "data:img/jpg;base64," + base64));
        //}
        // baseMapper.update(product, new QueryWrapper<Product>().lambda().eq(Product::getId, id));
        product.setMainurl(base64);
        doEsSomeThing(product, PlatformConstant.INDEX_NAME, id);
        return new R<>(true, "data:img/jpg;base64," + base64);
    }

    /**
     * 删除物料方法封装
     *
     * @param ids
     */
    private int delProductCommon(String ids) throws Exception {
        Product product = baseMapper.selectById(ids);
        if (product == null) {
            throw new MyException("id为{" + ids + "}的物料不存在");
        }
        product.setState(PlatformConstant.STATE_NO);
        // 同步es
        DeleteRequest deleteRequest = new DeleteRequest(PlatformConstant.INDEX_NAME, ids);
        restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
        return baseMapper.deleteById(ids);
    }

    /**
     * 上下架物料方法封装
     *
     * @param ids
     * @param shelfState
     */
    private Boolean shelfStateCommon(String ids, String shelfState) throws Exception {
        Product product = baseMapper.selectById(ids);
        if (product == null) {
            throw new MyException("id为{" + ids + "}的物料不存在");
        }
        product.setShelfstate(shelfState);
        doEsSomeThing(product, PlatformConstant.INDEX_NAME, ids);
        return update(Wrappers.<Product>lambdaUpdate()
                .set(Product::getShelfstate, shelfState)
                .eq(Product::getId, ids));
    }

    /**
     * ES索引修改
     *
     * @param product
     * @param indexName
     * @throws Exception
     */
    private void doEsSomeThing(Product product, String indexName, String id) throws Exception {
        UpdateRequest request = new UpdateRequest(indexName, id);
        request.timeout("1s");
        request.doc(JSON.toJSONString(product), XContentType.JSON);
        restHighLevelClient.update(request, RequestOptions.DEFAULT);
    }
}
